/**
 * Created by Administrator on 2017/4/18.
 */
import app from '../index.js';
import E from  './effect.js';

var obj = {};
obj.draw = function () {
  var pad = null;
  var graph = null;
  var lineLength = 10;
  var lines = null,width = 5000,height = 500,force = null,r = 10;
  function _force(contain) {
    _force.init();
    pad = contain ? contain : d3.select('svg');
    graph = pad.append('g').attr('class','graph');
    _force.zoom = d3.zoom().on('zoom',()=>graph.attr('transform', d3.event.transform));
    d3.select('svg').call(_force.zoom);
    return _force;
  }
  /*一些初始化的东西*/
  _force.init = function () {
    var arrowMarker = d3.select('svg').append("marker")
    .attr("id","arrow")
    .attr("markerUnits","strokeWidth")
    .attr("markerWidth",12)
    .attr("markerHeight",12)
    .attr("viewBox","0 0 24 24")
    .attr("refX",0)
    .attr("refY",12)
    .attr("orient","auto")
    ;
    var arrow_path = "M0,0 L0,24 L12,12 Z";
    // 定义箭头
    arrowMarker.append("path")
    .attr("d",arrow_path)
    .attr("fill","grey")
    ;
  };
  /*
   * 进行绘制的容器缩放事件（参数：d3元素）
   * */
  _force.zoomChange = function (w,h) {
    w = parseInt(w);
    h = parseInt(h);
    let objs = d3.zoomTransform(pad);
    objs.x = w/2;
    objs.y = h/2;
    objs.k = 1;
    this.zoom.transform(graph,objs);
  };

  /*
   * 绘制线的距离改变
   * */
  _force.lineLength = function (length) {
    lineLength = length;
    return this
  };
  _force.changeR = function (noder) {
    r = noder;
    return this
  };
  /*
   * 绘制的区域参数（[宽,高]）
   * */
  _force.size = function (arr) {
    width = arr[0];
    height = arr[1];
    _force.zoomChange(width,height);
    return this
  };

  /*
   * 进行线数据的处理(进行传入所有的lines数据)
   * */
  _force.lines = function (lineData) {
    lines = d3.forceLink(lineData)
    .id(function (d) {
      return d.id
    })
    .distance(lineLength)
    .strength(1)
    ;
    _force.drawLines(lineData);
  };
  /*
   * 进行线数据的处理(进行传入所有的nodes的数据)
   * */
  _force.nodes = function (nodeData) {
    force = d3.forceSimulation(nodeData)
    .force("link", lines)
    .force("charge", d3.forceManyBody().strength(-300).theta(1))
    .force("center", d3.forceCenter(width / 2, height / 2))
    ;
    force.alpha(0.1).alphaTarget(0.1).velocityDecay(0.1);
    _force.drawNodes(nodeData);
    force.on('tick',function () {
      graph.selectAll('.force_circle').attr('transform',function (d) {
        return 'translate(' + d.x + ',' + d.y + ')';
      }).on('dblclick',function (d) {
        d.fx = null;  d.fy = null;
      })
      ;
      _force.updateLine();
    });

  };

  /*
  * 更新连线
  * */
  _force.updateLine = function () {
    graph.selectAll('.force_line').attr('d',function (d) {
      var dx = d.target.x - d.source.x,
      dy = d.target.y - d.source.y,
      dr = Math.sqrt(dx * dx + dy * dy);
      return ['M', d.source.x + r * dx / dr , d.source.y + r * dy / dr ,
        'L', d.target.x - (r + r/2) * dx / dr , d.target.y - (r + r/2) * dy / dr].join(' ');
    })
  };

  /*
   * 进行绘图
   * */
  _force.drawLines = function (lines) {
    var ele = graph.selectAll('g.lineG').data(lines).enter().append('g').attr('class','lineG');
    ele.append('path').attr('class','force_line').attr('stroke','black').attr("marker-end","url(#arrow)");
  };
  _force.drawNodes = function (nodes) {
    function dragstart(d) {
      if (!d3.event.active) simulation.alphaTarget(0.3).restart(0.1);
      d.fx = d.x;   d.fy = d.y;
    }
    function dragging(d) {
      d.fx = d3.event.x;  d.fy = d3.event.y;
    }
    function dragged(d) {
      if (!d3.event.active) simulation.alphaTarget(0);
      d.fx = d3.event.x;  d.fy = d3.event.y;
    };
    var dragEvent = d3.drag().on('start',dragstart).on('drag',dragging).on('end',dragged);

    var ele = graph.selectAll('g.nodeG').data(nodes).enter().append('g').attr('class','nodeG');
    //添加球
    ele.append('circle')
    .attr('class','force_circle')
    .attr('r',r)
    .attr('fill',function (d) {
      return d.classColor || 'green'
    })
    .call(dragEvent)
    ;
  };

  /*
   * 进行数据的处理(进行传入所有的lines数据,还有线的长度)
   * */
  _force.start = function (nodeData,lineData) {
    _force.init();
    _force.lines(lineData);
    _force.nodes(nodeData);

  };

  return _force
};


export default {
  init:function () {
    app.app.factory('forceDraw',function () {
      return obj;
    });
  }
}